package ongd.servicios.persistencia;

import java.io.Serializable;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import ongd.negocio.gestion.Apadrinado;
import ongd.negocio.gestion.ApadrinadoPK;
import ongd.negocio.gestion.Entidad;
import ongd.negocio.gestion.Proyecto;
import ongd.negocio.gestion.Persona;
import ongd.servicios.persistencia.exceptions.NonexistentEntityException;
import ongd.servicios.persistencia.exceptions.PreexistingEntityException;

/**
 * Clase que contiene los método que para realizar operaciones
 * sobre la base de datos referente a la entidad Apadrinado.
 *
 * @author <a href="mailto:egi0002@alu.ubu.es">Elena García Iglesias</a>
 * @author <a href="mailto:cms0021@alu.ubu.es">Cristina Martínez Sanz</a>
 * @version 1.0 20120124
 *
 */
public class ApadrinadoJpaController extends AJPAControlador implements Serializable {
    /**
     * Objeto de tipo EntityManager.
     */
    private EntityManager em = null;

    /**
     * Constructor de la clase.
     * @param em EntityManager
     */
    public ApadrinadoJpaController(EntityManager em) {
        this.em = em;
    }    

    /**
     * Método que crea un objeto de tipo apadrinado en la base de datos.
     * @param entidad Objeto que crearemos 
     * @param et Booleano que indica si hay que iniciar la transacción
     * @throws PreexistingEntityException
     * @throws Exception 
     */
    @Override
    public void create(Entidad entidad, boolean et) throws PreexistingEntityException, Exception {
        Apadrinado apadrinado = (Apadrinado) entidad;
        if (apadrinado.getApadrinadoPK() == null) {
            apadrinado.setApadrinadoPK(new ApadrinadoPK());
        }
        apadrinado.getApadrinadoPK().setProyectoidProyecto(apadrinado.getProyecto().getIdProyecto());
        try {
            //Si et es falso significa que tengo que crear la transacción
            if (!et){
                em.getTransaction().begin();
            }
            Proyecto proyecto = apadrinado.getProyecto();
            if (proyecto != null) {
                proyecto = em.getReference(proyecto.getClass(), proyecto.getIdProyecto());
                apadrinado.setProyecto(proyecto);
            }
            Persona personaDNI = apadrinado.getPersonaDNI();
            if (personaDNI != null) {
                personaDNI = em.getReference(personaDNI.getClass(), personaDNI.getDni());
                apadrinado.setPersonaDNI(personaDNI);
            }
            em.persist(apadrinado);
            if (proyecto != null) {
                proyecto.getApadrinadoList().add(apadrinado);
                proyecto = em.merge(proyecto);
            }
            if (personaDNI != null) {
                personaDNI.getApadrinadoList().add(apadrinado);
                personaDNI = em.merge(personaDNI);
            }
            //Si et es falso significa que tengo que terminar la transaccion
            if (!et){
                em.getTransaction().commit();
            }
        } catch (Exception ex) {
            if (findEntidad(Apadrinado.class,apadrinado.getApadrinadoPK()) != null) {
                throw new PreexistingEntityException("Apadrinado " + apadrinado + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
//                em.close();
            }
        }
    }

    /**
     * Método que edita un objeto de tipo apadrinado en la base de datos.
     * @param entidad Entidad que editaremos
     * @param et Booleano que indica si hay que iniciar la transacción
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    @Override
    public void edit(Entidad entidad, boolean et) throws NonexistentEntityException, Exception {
        Apadrinado apadrinado = (Apadrinado) entidad;
        apadrinado.getApadrinadoPK().setProyectoidProyecto(apadrinado.getProyecto().getIdProyecto());
        try {
            //Si et es falso significa que tengo que crear la transacción
            if (!et){
                em.getTransaction().begin();
            }
            Apadrinado persistentApadrinado = em.find(Apadrinado.class, apadrinado.getApadrinadoPK());
            Proyecto proyectoOld = persistentApadrinado.getProyecto();
            Proyecto proyectoNew = apadrinado.getProyecto();
            Persona personaDNIOld = persistentApadrinado.getPersonaDNI();
            Persona personaDNINew = apadrinado.getPersonaDNI();
            if (proyectoNew != null) {
                proyectoNew = em.getReference(proyectoNew.getClass(), proyectoNew.getIdProyecto());
                apadrinado.setProyecto(proyectoNew);
            }
            if (personaDNINew != null) {
                personaDNINew = em.getReference(personaDNINew.getClass(), personaDNINew.getDni());
                apadrinado.setPersonaDNI(personaDNINew);
            }
            apadrinado = em.merge(apadrinado);
            if (proyectoOld != null && !proyectoOld.equals(proyectoNew)) {
                proyectoOld.getApadrinadoList().remove(apadrinado);
                proyectoOld = em.merge(proyectoOld);
            }
            if (proyectoNew != null && !proyectoNew.equals(proyectoOld)) {
                proyectoNew.getApadrinadoList().add(apadrinado);
                proyectoNew = em.merge(proyectoNew);
            }
            if (personaDNIOld != null && !personaDNIOld.equals(personaDNINew)) {
                personaDNIOld.getApadrinadoList().remove(apadrinado);
                personaDNIOld = em.merge(personaDNIOld);
            }
            if (personaDNINew != null && !personaDNINew.equals(personaDNIOld)) {
                personaDNINew.getApadrinadoList().add(apadrinado);
                personaDNINew = em.merge(personaDNINew);
            }
            //Si et es falso significa que tengo que terminar la transaccion
            if (!et){
                em.getTransaction().commit();
            }
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                ApadrinadoPK id = apadrinado.getApadrinadoPK();
                if (findEntidad(Apadrinado.class,id) == null) {
                    throw new NonexistentEntityException("The apadrinado with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
//                em.close();
            }
        }
    }

    /**
     * Método que borra un objeto de tipo apadrinado de la base de datos.
     * @param clase Clase correpondiente al objeto a borrar
     * @param id Clave primaria del objeto a borrar
     * @param et Booleano que indica si hay que iniciar la transaccion
     * @throws NonexistentEntityException 
     */
    @Override
    public void destroy(Class clase, Object id, boolean et) throws NonexistentEntityException {
        try {
            //Si et es falso significa que tengo que crear la transacción
            if (!et){
                em.getTransaction().begin();
            }
            Apadrinado apadrinado;
            try {
                apadrinado = (Apadrinado) em.getReference(clase, id);
                apadrinado.getApadrinadoPK();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The apadrinado with id " + id + " no longer exists.", enfe);
            }
            Proyecto proyecto = apadrinado.getProyecto();
            if (proyecto != null) {
                proyecto.getApadrinadoList().remove(apadrinado);
                proyecto = em.merge(proyecto);
            }
            Persona personaDNI = apadrinado.getPersonaDNI();
            if (personaDNI != null) {
                personaDNI.getApadrinadoList().remove(apadrinado);
                personaDNI = em.merge(personaDNI);
            }
            em.remove(apadrinado);
            //Si et es falso significa que tengo que terminar la transaccion
            if (!et){
                em.getTransaction().commit();
            }
        } finally {
            if (em != null) {
//                em.close();
            }
        }
    }

    /**
     * Método que busca un apadrinado en la base de datos.
     * @param cls Class correspondiente al objeto a buscar
     * @param id Clave primaria del objeto a buscar
     * @return apadrinado
     */
    @Override
    public Apadrinado findEntidad(Class cls, Object id) {
        try {
            return (Apadrinado) em.find(cls, id);
        } finally {
//            em.close();
        }
    }
}
